package com.portal.sso.client.filter;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.Header;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONUtil;
import com.portal.sso.core.config.SsoConfig;
import com.portal.sso.core.model.JwtModel;
import com.portal.sso.core.model.RequestModel;
import com.portal.sso.core.model.ResponseTModel;
import com.portal.sso.core.server.RequestServerHandler;
import com.portal.sso.core.server.VerificationTgtServer;
import com.portal.sso.core.util.CookieTools;
import com.portal.sso.core.util.RequestHeaderTools;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.connector.Response;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

@Slf4j
public class WebAppFilter extends HttpServlet implements Filter {
    @Autowired
    RequestServerHandler requestServerHandler;
    //认证中心服务器
    private String ssoServer;
    //退出url入口
    private String logoutPath;
    //未登录时跳转的地址，如果不设置则跳转认证中心的地址
    private  String loginPath;

    //排除拦截地址
    private String excludedPaths;
    //uri风格
    private String appId;
    @Autowired
    VerificationTgtServer verificationTgtServer;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        ssoServer = filterConfig.getInitParameter(SsoConfig.SSO_CLIENT_SERVER);
        logoutPath = filterConfig.getInitParameter(SsoConfig.SSO_CLIENT_LOGOUT_PATH);
        excludedPaths = filterConfig.getInitParameter(SsoConfig.SSO_CLIENT_EXCLUDED_PATHS);
        appId = filterConfig.getInitParameter(SsoConfig.SSO_APP_ID);
        loginPath = filterConfig.getInitParameter(SsoConfig.SSO_SERVER_LOGIN_PATHS);
        log.debug("过滤器init执行完毕");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) servletRequest;
        HttpServletResponse res = (HttpServletResponse) servletResponse;

        // make url
        String servletPath = req.getServletPath();
        RequestModel requestModel =   requestServerHandler.LoadModel(req);
        String tgt = requestModel.getTgt();
        // excluded path check
        if (excludedPaths != null && excludedPaths.trim().length() > 0) {
            for (String excludedPath : excludedPaths.split(",")) {
                String uriPattern = excludedPath.trim();


                if (StrUtil.startWith(servletPath, uriPattern)) {
                    // 属于排除资源，直接放行
                    filterChain.doFilter(servletRequest, servletResponse);
                    return;
                }

            }
        }

        // 退出时调用的逻辑
        if (logoutPath != null
                && logoutPath.trim().length() > 0
                && logoutPath.equals(servletPath)) {

            // 移除本地cookie
            CookieTools.clearCookieByName(res, SsoConfig.SSO_COOKIE_TGT);

            // 调用服务移除服务端tgt
            String logoutPageUrl = ssoServer.concat(SsoConfig.SSO_LOGOUT);
            if(StrUtil.isNotEmpty(tgt)){
                Map<String,String> map = new HashMap<String,String>();
                map.put(SsoConfig.SSO_PARAMETER_TGT,tgt);
                map.put(SsoConfig.SSO_APP_ID,appId);
                //添加tgt参数跳转
                logoutPageUrl= RequestHeaderTools.AddParaToUrl(logoutPageUrl,map,null);
            }
            res.sendRedirect(logoutPageUrl);
            return;
        }

        // 验证登录用户
        String userId = verificationTgtServer.Verification(ssoServer.concat(SsoConfig.SSO_VERSION_URL),tgt);


        // 重定向登录或提示登录信息
        if (userId == null) {

            String header = req.getHeader("content-type");
            boolean isJson = header != null && header.contains("json");
            if (isJson) {

                // json 消息
                res.setContentType("application/json;charset=utf-8");
                Map err_map = new HashMap<String,String>();
                err_map.put("code",SsoConfig.SSO_LOGIN_FAIL_RESULT.getCode());
                err_map.put("msg",SsoConfig.SSO_LOGIN_FAIL_RESULT.getMsg());
                res.getWriter().println(JSONUtil.toJsonStr(err_map));
                return;
            } else {
                //跳转登录时可以配置第三方登录地址loginPath。此时可以关闭sso认证中心的登录地址降低安全风险。
                if(loginPath!=null){
                    res.sendRedirect(loginPath);
                }else{
                    // total link
                    String link = req.getRequestURL().toString()+(req.getQueryString()!=null?"?"+req.getQueryString():"");
                    link=java.net.URLEncoder.encode(link, "UTF-8");
                    // redirect logout
                    String loginPageUrl = ssoServer.concat(SsoConfig.SSO_LOGIN)
                            + "?"
                            + SsoConfig.SSO_APP_ID+"="+appId
                            +"&"+SsoConfig.SSO_REDIRECT_URL + "=" + link;

                    res.sendRedirect(loginPageUrl);
                }

                return;
            }
        }
        // 用户标识传值到其他控制器
        servletRequest.setAttribute(SsoConfig.SSO_REQUEST_USER_ID, userId);
        CookieTools.addCookie(res,null,SsoConfig.SSO_COOKIE_PATH,SsoConfig.SSO_COOKIE_TGT,tgt,CookieTools.CLEAR_BROWSER_IS_CLOSED,true,false);

        filterChain.doFilter(servletRequest, servletResponse);
        return;
    }
}
